package com.kun.controller;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.kun.config.EntityRedisSerializer;
import com.kun.entity.Book;
import com.kun.entity.User;
import com.kun.service.UserService;
import com.kun.util.GenerateRandomNumber;
import com.kun.util.MD5ProducterUtil;
import com.kun.util.Snippet;

@Controller
public class SimpleController {
	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private UserService userServiceImpl;
	
	
	
	@Autowired  
	DefaultKaptcha defaultKaptcha;
	
	@Autowired
    protected RedisTemplate<String, Object> redisTemplate;
	
	@Autowired
	private SetOperations<String, Object> setOperations;
	
	
	@RequestMapping("/book")
    public String bookList(){
        return "/sort";
    }
	
	@RequestMapping("/wechatLogin")
    public String wechatLogin(){
        return "/wechatLogin";
    }
	
	@RequestMapping("/book/{id}")
    public String getOneBook(@PathVariable("id") int bookId,Model model){
		model.addAttribute("bookId", bookId);
        return "/book_detail";
    }
	
	@RequestMapping("/resetPassword")
    public String resetPassword(Model model,@RequestParam(name="email") String email,@RequestParam(name="token") String token,HttpServletRequest httpServletRequest){
		Cookie[] c = httpServletRequest.getCookies();
    	String uuid = "";
    	for(int i=0;i<c.length;i++){
    		Cookie cookie = c[i];
    		if("tokenMap".equals(cookie.getName())){
    			uuid = cookie.getValue();
    		}
    	}
    	if(!"".equals(uuid)){
    		redisTemplate.setValueSerializer(new EntityRedisSerializer());
    		@SuppressWarnings("unchecked")
    		Map<String, String> map=  (Map<String, String>) redisTemplate.opsForValue().get(uuid);
        	if(map!=null&&!map.isEmpty()){
        		if(token.equals(map.get(email))){
        			model.addAttribute("email", email);
        			model.addAttribute("token", token);
        	        return "resetPassword";
            	}
        	}
    	}
    	model.addAttribute("msg", "链接已失效，请重新提交申请！");
		return "fail";
    }
	
	
	@RequestMapping("/login")
    public String login(){
        return "login";
    }
	
	@RequestMapping("/adminLogin")
    public String adminLogin(){
        return "adminLogin";
    }
	
	@RequestMapping("/403")
    public String unauthorizedRole(){
        System.out.println("------没有权限-------");
        return "403";
    }
	
	final String REGEX_MOBILE = "^((17[0-9])|(14[0-9])|(13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$";
	final String REGEX_EMAIL = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
	
	@RequestMapping(value="toLogin",method=RequestMethod.POST)
	@ResponseBody
	public Map<String,Object> toLogin(@RequestParam(name="username") String username,@RequestParam(name="password") String password,
			String rememberMe,HttpServletRequest req,HttpServletResponse resp) {
	    Map<String, Object> resultMap = new LinkedHashMap<String, Object>();
	    if(!Pattern.matches(REGEX_MOBILE, username)&&!Pattern.matches(REGEX_EMAIL, username)){
	    	if(username.length()>18){
	    		resultMap.put("status", 500);
		        resultMap.put("message", "登录失败:请输入正确的账号");
		        return resultMap;
	    	}
		}
	    try {
	    	UsernamePasswordToken token = new UsernamePasswordToken(username, password);
	    	if("1".equals(rememberMe)){
	    		token.setRememberMe(true);
	    	}
	        SecurityUtils.getSubject().login(token);
	        Subject  currentUser = SecurityUtils.getSubject(); 
			User user = (User) currentUser.getPrincipal();
	        if(user.getState()==0){
	        	resultMap.put("status", 500);
		        resultMap.put("message", "登录失败：用户未激活！");
		        SecurityUtils.getSubject().logout();
		        return resultMap;
	        }
	        if(user.getState()==2){
	        	resultMap.put("status", 500);
		        resultMap.put("message", "登录失败：用户被禁用！");
		        SecurityUtils.getSubject().logout();
		        return resultMap;
	        }
	        resultMap.put("status", 200);
	        resultMap.put("message", "登录成功");
	        
	        //更新用户最后登录时间
	        
	        User user1 = new User();
	        user1.setId(user.getId());
	        user1.setLastLogDate(new Date());
	        userServiceImpl.updateUserByIdSelective(user1);
	        
	        //获取cookie保存的图书
	        Set<Book> sb = new HashSet<Book>();
			Cookie[] cookies = req.getCookies();
			if (null != cookies && cookies.length > 0) {
				for(int i=0;i<cookies.length;i++){
		    		Cookie cookie = cookies[i];
		    		if(("USER_BOOK_SET").equals(cookie.getName())){//该用户是否有保存书在cookie
		    			String cv = cookie.getValue();
		    			if(!"".equals(cv)&&cv!=null){
							try {
								sb = JSON.parseObject(URLDecoder.decode(cv, "UTF-8"), new TypeReference<Set<Book>>(){});
							} catch (UnsupportedEncodingException e) {
								e.printStackTrace();
								logger.error("解码发生错误。。。");
							}
		    			}
		    			break;
		    		}
		    	}
			}
			if(sb.size()>0){
				//登录后插入到缓存后删除cookie
				for(Book book:sb){
					if(book.getBookid()!=null){
						redisTemplate.setValueSerializer(new EntityRedisSerializer());
						setOperations.add(user.getUsername() + "USER_BOOK_SET", book.getBookid());
					}
				}
				Cookie cookie = new Cookie("USER_BOOK_SET",null);
	            cookie.setPath("/");
	            cookie.setMaxAge(0);
	            resp.addCookie(cookie);
			}
	    } catch (ExcessiveAttemptsException e) {  
            resultMap.put("status", 500);
	        resultMap.put("message", "登录失败多次，账户锁定10分钟");
        } catch (AuthenticationException e) {
        	resultMap.put("status", 500);
    		resultMap.put("message", "登录失败:账号或密码错误！");
	    } catch (Exception e) {
	        resultMap.put("message", "未知系统错误:" + e.getMessage());
	    }
	    return resultMap;
	}
	
	@RequestMapping(value="register",method =RequestMethod.POST)
	@ResponseBody
	public String register(@RequestParam(name="inputCode") String inputCode,User user,HttpServletRequest httpServletRequest){
		if(!Pattern.matches(REGEX_EMAIL, user.getEmail())){
			return "邮箱格式不正确";
		}
		
		//校验验证码
		Cookie[] c = httpServletRequest.getCookies();
    	String uuid = "";
    	for(int i=0;i<c.length;i++){
    		Cookie cookie = c[i];
    		if("CaptchaCode".equals(cookie.getName())){
    			uuid = cookie.getValue();
    		}
    	}
    	
    	String msg = "";
    	redisTemplate.setValueSerializer(new EntityRedisSerializer());
    	String validateCode =  (String) redisTemplate.opsForValue().get(uuid);
    	if(inputCode.toLowerCase().equals(validateCode)){
    		logger.info("注册邮箱："+user.getEmail()+"-pwd:"+user.getPassword());
    		User user1 = userServiceImpl.selectUserByLogUsername(user.getEmail());
        	if(user1!=null){
        		msg = "用户已存在";
        	}else{
        		int i = 0;
        		if(user.getPassword()!=null){
        			i = userServiceImpl.insertUser(user);
        		}
        		if(i>0){
        			msg = "注册成功";
        		}else{
        			msg = "注册失败";
        		}
        	}
		}else{
			msg = "验证码错误";
		}
		logger.info(msg);
		return msg;
	}
	
	
	
	@RequestMapping(value="toAdminLogin",method=RequestMethod.POST)
	@ResponseBody
	public Map<String,Object> toAdminLogin(String username, String password) {
	    Map<String, Object> resultMap = new LinkedHashMap<String, Object>();
	    try {
	    	UsernamePasswordToken token = new UsernamePasswordToken("@@@"+username+"!!!", password);
	        SecurityUtils.getSubject().login(token);
	        resultMap.put("status", 200);
	        resultMap.put("message", "登录成功");
	        
	        //更新管理员最后登录时间 
	        Subject  currentUser = SecurityUtils.getSubject(); 
			User user = (User) currentUser.getPrincipal();
	        User user1 = new User();
	        user1.setId(user.getId());
	        user1.setLastLogDate(new Date());
	        userServiceImpl.updateUserByIdSelective(user);
	    }  catch (DisabledAccountException e) {
	        resultMap.put("message", "登录失败：非管理员用户！");
	    }   catch (IncorrectCredentialsException e) {
	        resultMap.put("status", 500);
	        resultMap.put("message", "登录失败:用户名/密码错误");
	    } catch (ExcessiveAttemptsException e) {  
            resultMap.put("status", 500);
	        resultMap.put("message", "登录失败多次，账户锁定10分钟");
        }  catch (AuthenticationException e) {
	        resultMap.put("status", 500);
	        resultMap.put("message", "登录失败:用户名/密码错误");
	    }  catch (Exception e) {
	        resultMap.put("message", "未知系统错误:" + e.getMessage());
	    }
	    return resultMap;
	}
	
	
	/**
	* 退出
	 * @return
	 */
	@RequestMapping(value="logout")
	public String logout(){
	    String msg = "";
	    try {
	        //退出
	        SecurityUtils.getSubject().logout();
	        msg = "退出成功";
	    } catch (Exception e) {
	    	msg = "退出失败";
	        System.err.println(e.getMessage());
	    }
	    logger.info(msg);
	    return "login";
	}
	
	
	/**
	 * 生成图片验证码
	 * */
	@RequestMapping("/getCode")  
    public void getCode(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) throws Exception{  
             byte[] captchaChallengeAsJpeg = null;    
             ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();    
             try {    
             //生产验证码字符串
             String createText = defaultKaptcha.createText();  
             //保存到session中  
             httpServletRequest.getSession().setAttribute("vrifyCode", createText);
             //使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中  
             BufferedImage challenge = defaultKaptcha.createImage(createText);  
             ImageIO.write(challenge, "jpg", jpegOutputStream);  
             } catch (IllegalArgumentException e) {    
                 httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);    
                 return;    
             }   
         
             //定义response输出类型为image/jpeg类型，使用response输出流输出图片的byte数组  
             captchaChallengeAsJpeg = jpegOutputStream.toByteArray();    
             httpServletResponse.setHeader("Cache-Control", "no-store");    
             httpServletResponse.setHeader("Pragma", "no-cache");    
             httpServletResponse.setDateHeader("Expires", 0);    
             httpServletResponse.setContentType("image/jpeg");    
             ServletOutputStream responseOutputStream =    
             httpServletResponse.getOutputStream();    
             responseOutputStream.write(captchaChallengeAsJpeg);    
             responseOutputStream.flush(); 
             responseOutputStream.close();
    }
	
	/**
	 * 校验图片验证码
	 * */
	@RequestMapping("/validateCode")
	@ResponseBody
	public String validateCode(String inputCode,HttpServletRequest httpServletRequest){
		String vrifyCode = (String) httpServletRequest.getSession().getAttribute("vrifyCode");
		String msg = "";
		if(inputCode.toLowerCase().equals(vrifyCode)){
			msg = "true";
		}else{
			msg = "false";
		}
		logger.info(vrifyCode+"-"+inputCode.toLowerCase()+"-"+msg);
		return msg;
	} 
	
	/**
     * 重置密码
     * */
    @RequestMapping(value="submitResetPwd",method =RequestMethod.POST)
    @ResponseBody
    public String submitResetPwd(@RequestParam(name="email") String email,@RequestParam(name="token") String token,@RequestParam(name="password") String password,
    		HttpServletRequest httpServletRequest){
    	Cookie[] c = httpServletRequest.getCookies();
    	String uuid = "";
    	String msg = "false";
    	for(int i=0;i<c.length;i++){
    		Cookie cookie = c[i];
    		if("tokenMap".equals(cookie.getName())){
    			uuid = cookie.getValue();
    		}
    	}
    	redisTemplate.setValueSerializer(new EntityRedisSerializer());
    	@SuppressWarnings("unchecked")
		Map<String, String> map=  (Map<String, String>) redisTemplate.opsForValue().get(uuid);
    	if(map!=null&&!map.isEmpty()){
    		if(token.equals(map.get(email))){
        		User user = userServiceImpl.selectUserByLogUsername(email);
        		String realSalt = GenerateRandomNumber.getCharAndNumr(10);
        		user.setSalt(realSalt);
        		String MD5Password = MD5ProducterUtil.generate(password, user.getUsername()+user.getSalt());
        		user.setPassword(MD5Password);
        		int i = userServiceImpl.updateUserAllInfo(user);
        		if(i>0){
        			msg = "true";
        			redisTemplate.delete(uuid);
        		}
        	}
    	}else{
    		msg = "令牌错误或者已失效";
    	}
    	logger.info(msg);
    	return msg;
    }
	
    
	
	
	
	/** 
	 * 获得二维码 
	 * @param request <div>  
        				<h3 class="theme g-c-base">APP下载</h3>  
                  		<div class="app-iphone"><img src="<%=path%>/phoneversion/getTwoDimension.do" alt="" ></div>  
          				</div>  
	 * @param response 
	 * @param type 
	 */  
	@RequestMapping(value = "/qrCode",method={RequestMethod.POST,RequestMethod.GET})  
	public void getQrCode(HttpServletRequest request,HttpServletResponse response){  
		Snippet s = new Snippet();
	    try {
	        s.getTwoDimension("http://192.168.1.111:8088/getCode?a=1&b=kkk", response, 200, 200);  
	    } catch (IOException e) {  
	        e.printStackTrace();
	    }  
	}  
	
}